package org.lemon.transport.coap.client;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.lemon.transport.context.auth.ValidateDeviceCredentialsResponse;
import org.lemon.transport.coap.adapter.CoapTransportAdaptor;
import org.lemon.transport.coap.server.service.TransportConfigurationContainer;
import org.lemon.transport.context.data.device.Device;
import org.lemon.transport.context.data.device.PowerMode;
import org.server.transport.gen.SessionProto;
import org.server.transport.gen.TransportProto;

import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Data
public class CoapClientState {

    private final Long deviceId;
    private final Lock lock;

    private volatile TransportConfigurationContainer configuration;
    private volatile CoapTransportAdaptor adaptor;
    private volatile ValidateDeviceCredentialsResponse credentials;
    private volatile SessionProto.SessionInfoProto session;
    private volatile CoapClientContext.CoapSessionListener listener;
    private volatile CoapObservationState attrsObservationState;
    private volatile CoapObservationState rpcObservationState;
    private volatile int contentFormat;

    private TransportProto.AttributeUpdateNotificationMsg missedAttributeUpdates;

    private Long profileId;
    @Getter
    private PowerMode powerMode;

    @Getter
    private Long psmActivityTimer;

    @Getter
    private Long pagingTransmissionWindow;

    @Getter
    private Long e_drxCycle;

    /**
     * 最近一次上行数据时间
     */
    @Getter
    private long lastUplinkTime;

    @Getter
    @Setter
    private boolean asleep;
    @Getter
    @Setter
    private Future<Void> sleepTask;

    private boolean firstE_drxDownlink = true;


    public CoapClientState(Long deviceId) {
        this.deviceId = deviceId;
        this.lock = new ReentrantLock();
    }

    public void init(ValidateDeviceCredentialsResponse credentials) {
        this.credentials = credentials;
        this.profileId = credentials.getDeviceInfo().getDeviceProfileId();
        this.powerMode = credentials.getDeviceInfo().getPowerMode();
    }

    public boolean checkFirstDownlink() {
        boolean result = firstE_drxDownlink;
        firstE_drxDownlink = false;
        return result;
    }

    public void lock() {
        lock.lock();
    }

    public void unlock() {
        lock.unlock();
    }

    public long updateLastUplinkTime(long ts) {
        if (ts > lastUplinkTime) {
            this.lastUplinkTime = ts;
        }
        return lastUplinkTime;
    }

    public void onDeviceUpdate(Device device) {

        this.profileId = device.getDeviceProfileId();

    }

    public void addQueuedNotification(TransportProto.AttributeUpdateNotificationMsg msg) {

    }

    public TransportProto.AttributeUpdateNotificationMsg getAndClearMissedUpdates() {
        var result = this.missedAttributeUpdates;
        this.missedAttributeUpdates = null;
        return result;
    }
}
